package com.witmore.neutron.ai.mcp.server.trading.scheduler;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.witmore.neutron.ai.mcp.server.trading.db.entity.ScorpionUserStockRelationDO;
import com.witmore.neutron.ai.mcp.server.trading.db.mapper.ScorpionUserStockRelationMapper;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

/**
 * 动态异动预警定时任务调度器
 *
 * @author 豆子高
 * @since 2025-01-27
 */
//@Profile("prod")
@Slf4j
@Service
public class DynamicAlertTaskScheduler {

    @Autowired
    private TaskScheduler taskScheduler;

    @Autowired
    private ScorpionUserStockRelationMapper stockRelationMapper;

    @Autowired
    private StockAbnormalAlertTask stockAbnormalAlertTask;

    /**
     * 存储正在运行的定时任务
     * Key: userId_stockCode (例如: 1_000001)
     * Value: ScheduledFuture对象
     */
    private final Map<String, ScheduledFuture<?>> runningTasks = new ConcurrentHashMap<>();

    /**
     * 应用启动时初始化所有已开启的定时任务
     */
    @PostConstruct
    public void initScheduledTasks() {
        log.info("开始初始化异动预警定时任务...");

        try {
            // 查询所有开启预警推送的股票配置
            LambdaQueryWrapper<ScorpionUserStockRelationDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ScorpionUserStockRelationDO::getAlertPushEnabled, 1)
                    .eq(ScorpionUserStockRelationDO::getIsDeleted, (byte) 0)
                    .isNotNull(ScorpionUserStockRelationDO::getAlertConfig);

            List<ScorpionUserStockRelationDO> enabledConfigs = stockRelationMapper.selectList(queryWrapper);

            for (ScorpionUserStockRelationDO config : enabledConfigs) {
                startAlertTask(config);
            }

            log.info("异动预警定时任务初始化完成，共启动了 {} 个任务", runningTasks.size());

        } catch (Exception e) {
            log.error("初始化异动预警定时任务失败", e);
        }
    }

    /**
     * 启动指定配置的异动预警定时任务
     *
     * @param config 股票关联配置
     */
    public void startAlertTask(ScorpionUserStockRelationDO config) {
        if (config == null || config.getAlertPushEnabled() != 1) {
            log.warn("配置为空或未开启预警推送，跳过启动任务");
            return;
        }

        String taskKey = generateTaskKey(config.getUserId(), config.getStockCode());

        try {
            // 解析配置信息
            Integer pushFrequency = parsePushFrequency(config.getAlertConfig());
            if (pushFrequency == null || pushFrequency <= 0) {
                log.warn("推送频率配置无效，跳过启动任务: {}", taskKey);
                return;
            }

            // 如果任务已存在，先停止
            stopAlertTask(config.getUserId(), config.getStockCode());

            // 创建定时任务：每隔 pushFrequency 分钟执行一次
            String cronExpression = String.format("0 */%d * * * ?", pushFrequency);

            ScheduledFuture<?> scheduledTask = taskScheduler.schedule(
                () -> stockAbnormalAlertTask.executeAlertTask(config.getUserId(), config.getStockCode()),
                new CronTrigger(cronExpression)
            );

            runningTasks.put(taskKey, scheduledTask);

            log.info("启动异动预警定时任务成功: {} - 执行频率: 每{}分钟", taskKey, pushFrequency);

        } catch (Exception e) {
            log.error("启动异动预警定时任务失败: {}", taskKey, e);
        }
    }

    /**
     * 停止指定用户和股票的异动预警定时任务
     *
     * @param userId 用户ID
     * @param stockCode 股票代码
     */
    public void stopAlertTask(Long userId, String stockCode) {
        String taskKey = generateTaskKey(userId, stockCode);

        ScheduledFuture<?> task = runningTasks.remove(taskKey);
        if (task != null) {
            task.cancel(false);
            log.info("停止异动预警定时任务: {}", taskKey);
        }
    }

    /**
     * 更新指定配置的定时任务
     *
     * @param config 更新后的配置
     */
    public void updateAlertTask(ScorpionUserStockRelationDO config) {
        if (config == null) {
            return;
        }

        String taskKey = generateTaskKey(config.getUserId(), config.getStockCode());

        if (config.getAlertPushEnabled() != null && config.getAlertPushEnabled() == 1) {
            // 开启状态：启动或重启任务
            log.info("更新异动预警定时任务（开启）: {}", taskKey);
            startAlertTask(config);
        } else {
            // 关闭状态：停止任务
            log.info("更新异动预警定时任务（关闭）: {}", taskKey);
            stopAlertTask(config.getUserId(), config.getStockCode());
        }
    }

    /**
     * 批量更新用户的所有定时任务
     *
     * @param userId 用户ID
     */
    public void updateUserAlertTasks(Long userId) {
        log.info("批量更新用户异动预警定时任务: userId = {}", userId);

        try {
            // 查询用户的所有股票配置
            LambdaQueryWrapper<ScorpionUserStockRelationDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ScorpionUserStockRelationDO::getUserId, userId)
                    .eq(ScorpionUserStockRelationDO::getIsDeleted, (byte) 0);

            List<ScorpionUserStockRelationDO> userConfigs = stockRelationMapper.selectList(queryWrapper);

            for (ScorpionUserStockRelationDO config : userConfigs) {
                updateAlertTask(config);
            }

            log.info("批量更新用户异动预警定时任务完成: userId = {}, 处理配置数量: {}", userId, userConfigs.size());

        } catch (Exception e) {
            log.error("批量更新用户异动预警定时任务失败: userId = {}", userId, e);
        }
    }

    /**
     * 获取当前运行中的任务数量
     */
    public int getRunningTaskCount() {
        return runningTasks.size();
    }

    /**
     * 获取所有运行中的任务键
     */
    public String getRunningTaskKeys() {
        return String.join(", ", runningTasks.keySet());
    }

    /**
     * 应用关闭时清理所有定时任务
     */
    @PreDestroy
    public void shutdown() {
        log.info("开始清理异动预警定时任务...");

        runningTasks.values().forEach(task -> {
            try {
                task.cancel(false);
            } catch (Exception e) {
                log.warn("取消定时任务时发生异常", e);
            }
        });

        runningTasks.clear();
        log.info("异动预警定时任务清理完成");
    }

    /**
     * 生成任务键
     */
    private String generateTaskKey(Long userId, String stockCode) {
        return userId + "_" + stockCode;
    }

    /**
     * 从配置JSON中解析推送频率
     *
     * @param alertConfigJson 配置JSON字符串
     * @return 推送频率（分钟），解析失败返回null
     */
    private Integer parsePushFrequency(String alertConfigJson) {
        if (!StringUtils.hasText(alertConfigJson)) {
            return null;
        }

        try {
            JSONObject configObj = JSON.parseObject(alertConfigJson);
            return configObj.getInteger("pushFrequency");
        } catch (Exception e) {
            log.warn("解析推送频率配置失败: {}", alertConfigJson, e);
            return null;
        }
    }
}
